#include <config.h>
#include <render.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <text_reader.h>
#include <fonts_manager.h>
#include <encoding_manager.h>
#include <picfmt_manager.h>
#include <file.h>
#include <unistd.h>


/* 图标是一个正方体: "返回"按钮 */
#define TEXT_PAGE_ICON_HEIGHT   40
#define TEXT_PAGE_ICON_WIDTH    40

#define BUTTON_RETURN_INDEX      0

static PT_VideoMem g_ptTextPageVideoMem;
static T_TextContent g_tTextContent;

static int g_iXres, g_iYres, g_iBpp;

/* 菜单的区域 */
static T_Layout g_atTextPageIconsLayout[] = {
    {0, 0, 0, 0, "return.bmp"},
    {0, 0, 0, 0, NULL},
};

static T_PageLayout g_tTextPageLayout = {
    .iMaxTotalBytes = 0,
    .atLayout       = g_atTextPageIconsLayout,
};

/**********************************************************************
 * 函数名称： TextPageGetInputEvent
 * 功能描述： 获取输入数据，并判断输入事件位于哪一个图标上
 * 输入参数： ptPageLayout - 内含多个图标的显示区域
 * 输出参数： ptInputEvent - 内含得到的输入数据
 * 返 回 值： -1     - 输入数据不位于任何一个图标之上
 *            其他值 - 输入数据所落在的图标
 ***********************************************************************/
static int TextPageGetInputEvent(PT_PageLayout ptPageLayout, PT_InputEvent ptInputEvent)
{
    return GenericGetInputEvent(ptPageLayout, ptInputEvent);
}

/**********************************************************************
 * 函数名称： TextPageCalcLayout
 * 功能描述： 计算页面中各图标座标值
 * 输入参数： 无
 * 输出参数： ptPageLayout - 内含各图标的左上角/右下角座标值
 * 返 回 值： 无
 ***********************************************************************/
static void TextPageCalcLayout(PT_PageLayout ptPageLayout)
{
    PT_Layout atLayout = ptPageLayout->atLayout;
    GetDispResolution(&g_iXres, &g_iYres, &g_iBpp);
    
    /* 返回按钮 */
    atLayout[0].iTopLeftX  = 0;
    atLayout[0].iTopLeftY  = 0;
    atLayout[0].iBotRightX = TEXT_PAGE_ICON_WIDTH - 1;
    atLayout[0].iBotRightY = TEXT_PAGE_ICON_HEIGHT - 1;
    
    ptPageLayout->iBpp = g_iBpp;
    
    /* 计算所需最大内存 */
    int iTmpTotalBytes = (atLayout[0].iBotRightX - atLayout[0].iTopLeftX + 1) * 
                         (atLayout[0].iBotRightY - atLayout[0].iTopLeftY + 1) * 
                         g_iBpp / 8;
    
    ptPageLayout->iMaxTotalBytes = iTmpTotalBytes;
}

/**********************************************************************
 * 函数名称： PutPixel
 * 功能描述： 在指定位置画一个像素点
 * 输入参数： ptVideoMem - 显存
 *            iX, iY - 坐标
 *            color - 颜色
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void PutPixel(PT_VideoMem ptVideoMem, int x, int y, unsigned int color)
{
    unsigned char *fb;
    unsigned short *p16;
    unsigned int *p32;
    
    if (!ptVideoMem || !ptVideoMem->tPixelDatas.aucPixelDatas)
        return;
    
    if (x < 0 || x >= ptVideoMem->tPixelDatas.iWidth || 
        y < 0 || y >= ptVideoMem->tPixelDatas.iHeight)
        return;
    
    fb = ptVideoMem->tPixelDatas.aucPixelDatas + y * ptVideoMem->tPixelDatas.iLineBytes + x * ptVideoMem->tPixelDatas.iBpp / 8;
    
    switch (ptVideoMem->tPixelDatas.iBpp)
    {
        case 8:
            *fb = color;
            break;
            
        case 16:
            p16 = (unsigned short *)fb;
            /* RGB565 */
            *p16 = ((color >> 19) & 0x1f) << 11 | ((color >> 10) & 0x3f) << 5 | ((color >> 3) & 0x1f);
            break;
            
        case 32:
            p32 = (unsigned int *)fb;
            *p32 = color;
            break;
            
        default:
            DBG_PRINTF("Can't support %d bpp\n", ptVideoMem->tPixelDatas.iBpp);
            break;
    }
}

/**********************************************************************
 * 函数名称： FillRect
 * 功能描述： 填充矩形区域
 * 输入参数： ptVideoMem - 显存
 *            x, y - 左上角坐标
 *            width, height - 宽高
 *            color - 颜色
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void FillRect(PT_VideoMem ptVideoMem, int x, int y, int width, int height, unsigned int color)
{
    unsigned char *pucDst;
    int i;
    
    if (!ptVideoMem || !ptVideoMem->tPixelDatas.aucPixelDatas)
        return;
    
    /* 裁剪坐标，确保不越界 */
    if (x < 0) { width += x; x = 0; }
    if (y < 0) { height += y; y = 0; }
    if (x + width > ptVideoMem->tPixelDatas.iWidth) 
        width = ptVideoMem->tPixelDatas.iWidth - x;
    if (y + height > ptVideoMem->tPixelDatas.iHeight)
        height = ptVideoMem->tPixelDatas.iHeight - y;
    
    /* 如果经过裁剪后宽高为0或负数，则直接返回 */
    if (width <= 0 || height <= 0)
        return;
    
    switch (ptVideoMem->tPixelDatas.iBpp)
    {
        case 8:
            /* 8位色深 - 每行直接使用memset */
            for (i = 0; i < height; i++)
            {
                pucDst = ptVideoMem->tPixelDatas.aucPixelDatas + (y + i) * ptVideoMem->tPixelDatas.iLineBytes + x;
                memset(pucDst, color, width);
            }
            break;
        
        case 16:
            /* 16位色深 - 直接设置内存 */
            {
                unsigned short color16 = ((color >> 19) & 0x1f) << 11 | ((color >> 10) & 0x3f) << 5 | ((color >> 3) & 0x1f);
                for (i = 0; i < height; i++)
                {
                    unsigned short *p16 = (unsigned short *)(ptVideoMem->tPixelDatas.aucPixelDatas + 
                                        (y + i) * ptVideoMem->tPixelDatas.iLineBytes + x * 2);
                    int j;
                    for (j = 0; j < width; j++)
                    {
                        *p16++ = color16;
                    }
                }
            }
            break;
        
        case 32:
            /* 32位色深 - 直接设置内存 */
            for (i = 0; i < height; i++)
            {
                unsigned int *p32 = (unsigned int *)(ptVideoMem->tPixelDatas.aucPixelDatas + 
                                   (y + i) * ptVideoMem->tPixelDatas.iLineBytes + x * 4);
                int j;
                for (j = 0; j < width; j++)
                {
                    *p32++ = color;
                }
            }
            break;
        
        default:
            /* 不支持的色深，使用原始方法 */
            {
                int j;
                for (i = 0; i < height; i++)
                {
                    for (j = 0; j < width; j++)
                    {
                        PutPixel(ptVideoMem, x + j, y + i, color);
                    }
                }
            }
            break;
    }
}


/**********************************************************************
 * 函数名称： DrawChar
 * 功能描述： 绘制单个字符
 * 输入参数： ptVideoMem - 显存
 *            x, y - 左上角坐标
 *            dwCode - 字符编码(UTF-8或ASCII)
 *            color - 颜色
 * 输出参数： 无
 * 返 回 值： 字符宽度
 ***********************************************************************/
static int DrawChar(PT_VideoMem ptVideoMem, int x, int y, unsigned int dwCode, unsigned int color)
{
    int i, j;
    int char_width = 8;      /* ASCII字符宽度 */
    int char_height = 16;    /* 字符高度 */
    int chinese_width = 16;  /* 中文字符宽度 */
    T_FontBitMap tFontBitMap;
    int iError;
    
    /* 尝试使用系统字体渲染字符 */
    memset(&tFontBitMap, 0, sizeof(tFontBitMap));
    tFontBitMap.iCurOriginX = x;
    tFontBitMap.iCurOriginY = y;
    
    /* 先尝试调用字体管理器获取字符位图 */
    iError = GetFontBitmap(dwCode, &tFontBitMap);
    if (iError == 0 && tFontBitMap.pucBuffer != NULL)
    {
       // DBG_PRINTF("GetFontBitmap returned: %d\n", iError);
       // DBG_PRINTF("FontBitMap details: Origin(%d,%d), LeftTop(%d,%d), RightBottom(%d,%d)\n", 
       //            tFontBitMap.iCurOriginX, tFontBitMap.iCurOriginY,
       //            tFontBitMap.iXLeft, tFontBitMap.iYTop,
       //            tFontBitMap.iXMax, tFontBitMap.iYMax);
       // DBG_PRINTF("Pitch: %d, NextOrigin: %d, Buffer: %p\n", 
       //            tFontBitMap.iPitch, tFontBitMap.iNextOriginX, tFontBitMap.pucBuffer);
        
        /* 注意：判断 iYTop 的合法性，防止负数导致的内存访问越界 */
        if (tFontBitMap.iYTop < 0)
            tFontBitMap.iYTop = 0;
        
        
       // DBG_PRINTF("Starting to draw bitmap with dimensions: width=%d, height=%d\n", 
       //            tFontBitMap.iXMax - tFontBitMap.iXLeft, tFontBitMap.iYMax - tFontBitMap.iYTop);
        
       /* 逐像素绘制字体位图 - 根据位图数据显示字符 */
       int x;
       int y;
       unsigned char ucByte = 0;
       int i = 0;
       int bit;
       
       if (tFontBitMap.iBpp == 1)
       {
           for (y = tFontBitMap.iYTop; y < tFontBitMap.iYMax; y++)
           {
               i = (y - tFontBitMap.iYTop) * tFontBitMap.iPitch;
               for (x = tFontBitMap.iXLeft, bit = 7; x < tFontBitMap.iXMax; x++)
               {
                   if (bit == 7)
                   {
                       ucByte = tFontBitMap.pucBuffer[i++];
                   }
                   
                   if (ucByte & (1<<bit))
                   {
                       PutPixel(ptVideoMem, x, y, color);
                   }
                   else
                   {
                       /* 使用背景色，不用绘制 */
                       // PutPixel(ptVideoMem, x, y, 0xFFFFFF); /* 白色背景 */
                   }
                   bit--;
                   if (bit == -1)
                   {
                       bit = 7;
                   }
               }
           }
       }
       else if (tFontBitMap.iBpp == 8)
       {
           for (y = tFontBitMap.iYTop; y < tFontBitMap.iYMax; y++)
               for (x = tFontBitMap.iXLeft; x < tFontBitMap.iXMax; x++)
               {
                   if (tFontBitMap.pucBuffer[i++])
                       PutPixel(ptVideoMem, x, y, color);
               }
       }
       else
       {
           DBG_PRINTF("DrawChar error, can't support %d bpp\n", tFontBitMap.iBpp);
       }
        
        /* 返回字符的宽度 */
        return tFontBitMap.iNextOriginX - tFontBitMap.iCurOriginX;
    }
    
    /* 如果字体管理器失败，使用我们自己的简单渲染方法 */
    
    /* 对于ASCII字符和基本拉丁字符范围(0-127) */
    if (dwCode < 128)
    {
        /* ASCII可显示字符范围: 32-126 */
        if (dwCode < 32 || dwCode > 126)
        {
            /* 绘制一个方块表示无法显示的字符 */
            for (j = 0; j < char_height; j++)
            {
                for (i = 0; i < char_width; i++)
                {
                    if (j == 0 || j == char_height-1 || i == 0 || i == char_width-1)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                }
            }
            return char_width;
        }
        
        
        /* 如果无法使用字体数据，使用简单的字符绘制方法 */
        for (j = 0; j < char_height; j++)
        {
            for (i = 0; i < char_width; i++)
            {
                /* 不同的字符使用不同的显示模式 */
                if (dwCode == 'I' || dwCode == 'l' || dwCode == 'i' || dwCode == '1')
                {
                    /* 垂直线 */
                    if (i == char_width/2)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                }
                else if (dwCode == '-' || dwCode == '_')
                {
                    /* 水平线 */
                    if (j == char_height*2/3)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                }
                else if (dwCode == '|' || dwCode == '(' || dwCode == ')')
                {
                    /* 竖线 */
                    if (dwCode == '(' && i == char_width/3)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                    else if (dwCode == ')' && i == char_width*2/3)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                    else if (dwCode == '|' && i == char_width/2)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                }
                else
                {
                    /* 默认绘制矩形框 */
                    if ((i == 1 || i == char_width-2) && (j >= 2 && j <= char_height-3))
                        PutPixel(ptVideoMem, x+i, y+j, color);
                    else if ((j == 2 || j == char_height-3) && (i >= 1 && i <= char_width-2))
                        PutPixel(ptVideoMem, x+i, y+j, color);
                    else if (dwCode == 'A' && j == char_height/2 && i >= 1 && i <= char_width-2)
                        PutPixel(ptVideoMem, x+i, y+j, color);
                }
            }
        }
        
        return char_width;
    }
    else
    {
        /* 中文字符或其他Unicode字符 - 绘制一个简单的方框 */
        for (j = 0; j < char_height; j++)
        {
            for (i = 0; i < chinese_width; i++)
            {
                /* 绘制外框和简单的内部结构，形成类似"口"的形状 */
                if (i == 0 || i == chinese_width-1 || j == 0 || j == char_height-1 ||
                    (i == chinese_width/2 && j > 2 && j < char_height-3) ||
                    (j == char_height/2 && i > 2 && i < chinese_width-3))
                {
                    PutPixel(ptVideoMem, x+i, y+j, color);
                }
            }
        }
        
        return chinese_width; /* 中文字符宽度为ASCII字符的两倍 */
    }
}

/**********************************************************************
 * 函数名称： DrawText
 * 功能描述： 绘制文本
 * 输入参数： ptVideoMem - 显存
 *            x, y - 左上角坐标
 *            text - 文本
 *            color - 颜色
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void DrawText(PT_VideoMem ptVideoMem, int x, int y, const char *text, unsigned int color)
{
    int i = 0;
    int pos_x = x;
    unsigned char c;
    unsigned int dwCode;
    
    if (!text)
        return;
    
    while (text[i])
    {
        c = text[i];
        
        /* 处理UTF-8编码 */
        if ((c & 0x80) == 0)  /* ASCII字符 */
        {
            dwCode = c;
            i += 1;
        }
        else if ((c & 0xE0) == 0xC0)  /* 2字节UTF-8 */
        {
            if (i+1 < strlen(text))
            {
                dwCode = ((c & 0x1F) << 6) | (text[i+1] & 0x3F);
                i += 2;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                dwCode = '?';
            }
        }
        else if ((c & 0xF0) == 0xE0)  /* 3字节UTF-8 */
        {
            if (i+2 < strlen(text))
            {
                dwCode = ((c & 0x0F) << 12) | ((text[i+1] & 0x3F) << 6) | (text[i+2] & 0x3F);
                i += 3;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                dwCode = '?';
            }
        }
        else if ((c & 0xF8) == 0xF0)  /* 4字节UTF-8 */
        {
            if (i+3 < strlen(text))
            {
                dwCode = ((c & 0x07) << 18) | ((text[i+1] & 0x3F) << 12) | 
                         ((text[i+2] & 0x3F) << 6) | (text[i+3] & 0x3F);
                i += 4;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                dwCode = '?';
            }
        }
        else
        {
            /* 无效的UTF-8序列 */
            dwCode = '?';
            i += 1;
        }
        
        /* 特殊字符处理 */
        if (dwCode == '\n')
        {
            pos_x = x;
            y += 16;
            continue;
        }
        
        if (dwCode == '\r')
        {
            continue;
        }
        
        if (dwCode == '\t')
        {
            pos_x += 32; /* 4个字符的宽度 */
            continue;
        }
        
        /* 超出屏幕宽度后自动换行 */
        if (pos_x > g_iXres - 20)
        {
            pos_x = x;
            y += 16;
        }
        
        /* 绘制字符 */
        pos_x += DrawChar(ptVideoMem, pos_x, y, dwCode, color);
    }
}


/**********************************************************************
 * 函数名称： DrawTextRange
 * 功能描述： 绘制指定长度范围内的文本
 * 输入参数： ptVideoMem - 显存
 *            x, y - 左上角坐标
 *            text - 文本开始指针
 *            maxLen - 最大处理的字节数
 *            color - 颜色
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void DrawTextRange(PT_VideoMem ptVideoMem, int x, int y, const char *text, int maxLen, unsigned int color)
{
    int i = 0;
    int pos_x = x;
    unsigned char c;
    unsigned int dwCode;
    int bytesProcessed = 0;
    
    if (!text || maxLen <= 0)
        return;
    
    while (text[i] && bytesProcessed < maxLen)
    {
        c = text[i];
        
        /* 处理UTF-8编码 */
        if ((c & 0x80) == 0)  /* ASCII字符 */
        {
            dwCode = c;
            i += 1;
            bytesProcessed += 1;
        }
        else if ((c & 0xE0) == 0xC0)  /* 2字节UTF-8 */
        {
            if (i+1 < maxLen)
            {
                dwCode = ((c & 0x1F) << 6) | (text[i+1] & 0x3F);
                i += 2;
                bytesProcessed += 2;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                bytesProcessed += 1;
                dwCode = '?';
            }
        }
        else if ((c & 0xF0) == 0xE0)  /* 3字节UTF-8 */
        {
            if (i+2 < maxLen)
            {
                dwCode = ((c & 0x0F) << 12) | ((text[i+1] & 0x3F) << 6) | (text[i+2] & 0x3F);
                i += 3;
                bytesProcessed += 3;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                bytesProcessed += 1;
                dwCode = '?';
            }
        }
        else if ((c & 0xF8) == 0xF0)  /* 4字节UTF-8 */
        {
            if (i+3 < maxLen)
            {
                dwCode = ((c & 0x07) << 18) | ((text[i+1] & 0x3F) << 12) | 
                         ((text[i+2] & 0x3F) << 6) | (text[i+3] & 0x3F);
                i += 4;
                bytesProcessed += 4;
            }
            else
            {
                i += 1;  /* 不完整的UTF-8序列 */
                bytesProcessed += 1;
                dwCode = '?';
            }
        }
        else
        {
            /* 无效的UTF-8序列 */
            dwCode = '?';
            i += 1;
            bytesProcessed += 1;
        }
        
        /* 特殊字符处理 */
        if (dwCode == '\n')
        {
            pos_x = x;
            y += 16;
            continue;
        }
        
        if (dwCode == '\r')
        {
            continue;
        }
        
        if (dwCode == '\t')
        {
            pos_x += 32; /* 4个字符的宽度 */
            continue;
        }
        
        /* 超出屏幕宽度后自动换行 */
        if (pos_x > g_iXres - 20)
        {
            pos_x = x;
            y += 16;
        }
        
        /* 绘制字符 */
        pos_x += DrawChar(ptVideoMem, pos_x, y, dwCode, color);
    }
}

/**********************************************************************
 * 函数名称： ShowTextPage
 * 功能描述： 显示文本页面
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void ShowTextPage(void)
{
    char strTitle[128] = "Text Viewer";
    int iTextY;
    

    DBG_PRINTF("GetVideoMem OK!\n");
    if (g_ptTextPageVideoMem == NULL)
    {
        DBG_PRINTF("can't get video mem for text page!\n");
        return;
    }
    
    /* 2. 计算图标坐标 */
    if (g_atTextPageIconsLayout[0].iTopLeftX == 0)
    {
        TextPageCalcLayout(&g_tTextPageLayout);
    }
    DBG_PRINTF("TextPageCalcLayout OK!\n");
    
    /* 3. 清空整个显存 */
    FillRect(g_ptTextPageVideoMem, 0, 0, g_iXres, g_iYres, 0xFFFFFF); /* 白色背景 */
    DBG_PRINTF("FillRect OK!\n");
    
    /* 4. 绘制返回按钮 */
    /* 绘制一个简单的返回图标 */
    FillRect(g_ptTextPageVideoMem, 
            g_atTextPageIconsLayout[0].iTopLeftX, 
            g_atTextPageIconsLayout[0].iTopLeftY, 
            g_atTextPageIconsLayout[0].iBotRightX - g_atTextPageIconsLayout[0].iTopLeftX + 1, 
            g_atTextPageIconsLayout[0].iBotRightY - g_atTextPageIconsLayout[0].iTopLeftY + 1, 
            0x0000FF); /* 蓝色返回按钮 */
    
    /* 5. 显示标题 */
    if (g_tTextContent.pText && g_tTextContent.iTextLen > 0)
    {
        snprintf(strTitle, sizeof(strTitle), "Text Viewer - %d bytes", g_tTextContent.iTextLen);
    }
    DBG_PRINTF("snprintf OK!\n");
    DrawText(g_ptTextPageVideoMem, 100, 10, strTitle, 0x0000FF); /* 蓝色标题 */
    
    /* 6. 显示文本内容 */
    if (g_tTextContent.pText && g_tTextContent.iTextLen > 0)
    {
        /* 有效的显示区域 */
        int iStart = g_tTextContent.iOffsetCurDispStart;
        int iEnd = g_tTextContent.iOffsetCurDispEnd;
        
        /* 边界检查 */
        if (iStart < 0) iStart = 0;
        if (iStart >= g_tTextContent.iTextLen) iStart = 0;
        if (iEnd <= iStart) iEnd = g_tTextContent.iTextLen;
        if (iEnd > g_tTextContent.iTextLen) iEnd = g_tTextContent.iTextLen;
        
        DBG_PRINTF("ShowTextPage: Showing text from %d to %d\n", iStart, iEnd);
        
        /* 直接绘制，无需额外分配内存 */
        iTextY = TEXT_PAGE_ICON_HEIGHT + 10;
        
        /* 使用修改版DrawText函数，只绘制指定范围内的文本 */
        DrawTextRange(g_ptTextPageVideoMem, 10, iTextY, 
                    g_tTextContent.pText + iStart, iEnd - iStart, 0x000000);
        
        /* 显示页码信息 */
        char strPageInfo[64];
        snprintf(strPageInfo, sizeof(strPageInfo), "Page %d/%d", 
                 (iStart / 1000) + 1, 
                 (g_tTextContent.iTextLen + 999) / 1000);
                 
        DrawText(g_ptTextPageVideoMem, g_iXres - 150, g_iYres - 20, strPageInfo, 0x0000FF);
    }
    else
    {
        /* 显示无文本提示 */
        DrawText(g_ptTextPageVideoMem, 200, 200, "No text content", 0xFF0000); /* 红色提示 */
    }
    DBG_PRINTF("DrawText OK!\n");
    
    /* 7. 刷到屏幕上 */
    FlushVideoMemToDev(g_ptTextPageVideoMem);
    DBG_PRINTF("FlushVideoMemToDev OK!\n");
}

/**********************************************************************
 * 函数名称： TextPageRun
 * 功能描述： 运行文本查看页面
 * 输入参数： ptParentPageParams - 内含上一个页面(父页面)的参数
 * 输出参数： 无
 * 返 回 值： 无
 ***********************************************************************/
static void TextPageRun(PT_PageParams ptParentPageParams)
{
    T_InputEvent tInputEvent;
    T_InputEvent tInputEventPre;
    int iIndex;
    int bButtonPressed = 0;
    int iIndexPressed = -1;
    int bTextChanged = 0;
    int iError;
    
    T_FileMap tFileMap;
    
    DBG_PRINTF("TextPageRun: starting\n");
    
    /* 1. 清空全局文本内容结构，确保安全 */
    if (g_tTextContent.pText) {
        free(g_tTextContent.pText);
    }
    memset(&g_tTextContent, 0, sizeof(g_tTextContent));
    
    /* 2. 初始化tFileMap */
    memset(&tFileMap, 0, sizeof(tFileMap));
    strncpy(tFileMap.strFileName, ptParentPageParams->strCurPictureFile, sizeof(tFileMap.strFileName) - 1);
    tFileMap.strFileName[sizeof(tFileMap.strFileName) - 1] = '\0';
    
    iError = MapFile(&tFileMap);
    if (iError)
    {
        DBG_PRINTF("MapFile %s error: %d\n", tFileMap.strFileName, iError);
        return;
    }
    
    DBG_PRINTF("TextPageRun: Getting text from file, size: %d\n", tFileMap.iFileSize);
    
    /* 4. 获取文本内容 */
    iError = GetTextFromFile(&tFileMap, &g_tTextContent);
    UnMapFile(&tFileMap);  /* 文件内容已经复制到g_tTextContent，可以解除映射 */
    
    if (iError)
    {
        DBG_PRINTF("GetTextFromFile error: %d\n", iError);
        return;
    }
    
    DBG_PRINTF("TextPageRun: Text content loaded, length: %d\n", g_tTextContent.iTextLen);
    
    /* 添加错误处理，确保获取了有效内容 */
    if (!g_tTextContent.pText || g_tTextContent.iTextLen <= 1)
    {
        DBG_PRINTF("ERROR: Failed to get valid text content\n");
        FreeTextContent(&g_tTextContent);
        return;
    }
    
    /* 5. 计算初始显示内容 */
    g_tTextContent.iOffsetCurDispStart = 0;
    g_tTextContent.iOffsetCurDispEnd = 0;
    
    /* 每次初始化时尝试一次翻页，确保内容准备好了 */
    TextPageDown(&g_tTextContent);
    DBG_PRINTF("try pagedown ok\n");
    /* 6. 获得显存 */
    g_ptTextPageVideoMem = GetVideoMem(ID("text"), 1);
    /* 7. 显示文本页面 */
    ShowTextPage();
    DBG_PRINTF("try ShowTextPage ok\n");

    
    /* 8. 处理输入事件 */
    tInputEventPre.tTime.tv_sec = 0;
    tInputEventPre.tTime.tv_usec = 0;
    
    while (1)
    {
        /* 先减少CPU占用率 */
        usleep(3000);
        
        /* 获取输入事件 */
        iIndex = TextPageGetInputEvent(&g_tTextPageLayout, &tInputEvent);
        DBG_PRINTF("TextPageGetInputEvent OK\n", tInputEvent.iType);
        DBG_PRINTF("iIndex=%d\n",iIndex);
        
        /* 计算布局数组中的元素数量 */
        int iLayoutNum = 0;
        while (g_tTextPageLayout.atLayout[iLayoutNum].strIconName && iIndex == 0)
        {
            iLayoutNum++;
        }
        /* 处理菜单选项 */
        if (iIndex == 0)
        {
            DBG_PRINTF("fist if=%d\n", tInputEvent.iType);
            /* 处理已经按下的按钮 */
            if (bButtonPressed)
            {
                if (iIndexPressed != iIndex)
                {
                    /* 释放之前的按钮 */
                    ReleaseButton(&g_atTextPageIconsLayout[iIndexPressed]);
                    bButtonPressed = 0;
                }
            }
            
            if (!bButtonPressed && tInputEvent.iPressure)
            {
                /* 按下按钮 */
                bButtonPressed = 1;
                iIndexPressed = iIndex;
                tInputEventPre = tInputEvent;
                PressButton(&g_atTextPageIconsLayout[iIndex]);
            }
            
            /* 如果按钮释放 */
            if (bButtonPressed && (tInputEvent.iPressure == 0))
            {
                bButtonPressed = 0;
                ReleaseButton(&g_atTextPageIconsLayout[iIndexPressed]);
                
                if (iIndexPressed == BUTTON_RETURN_INDEX)
                {
                    /* 点击了"返回"按钮，退出 */
                    if (g_ptTextPageVideoMem) {
                        PutVideoMem(g_ptTextPageVideoMem);
                        g_ptTextPageVideoMem = NULL;
                    }
                    DBG_PRINTF("Return button pressed, exiting text page\n");
                    break;
                }
            }
        } 
        else if (tInputEvent.iType == INPUT_TYPE_TOUCHSCREEN)
        {
            DBG_PRINTF("else if=%d\n", tInputEvent.iType);
            /* 处理触屏操作 */
            if (tInputEvent.iPressure)
            {
                /* 记录按下时的位置 */
                tInputEventPre = tInputEvent;
            }
            else
            {
                /* 松开时进行处理 */
                static struct timeval tPreTime = {0, 0};
                
                /* 添加防抖处理，忽略500ms内的连续点击 */
                if (tPreTime.tv_sec != 0)
                {
                    int iPreMs = tPreTime.tv_sec * 1000 + tPreTime.tv_usec / 1000;
                    int iNowMs = tInputEvent.tTime.tv_sec * 1000 + tInputEvent.tTime.tv_usec / 1000;
                    
                    if (iNowMs <= iPreMs + 30)
                    {
                        /* 500ms内的连续点击，忽略 */
                        continue;
                    }
                }
                
                /* 记录本次点击时间，用于防抖 */
                tPreTime = tInputEvent.tTime;
                
                /* 检测点击位置在屏幕左边还是右边 */
                int iXres, iYres, iBpp;
                GetDispResolution(&iXres, &iYres, &iBpp);
                
                if (tInputEvent.iX < iXres / 2)
                {
                    /* 点击了左半边，上翻页 */
                    DBG_PRINTF("Left side clicked, paging up\n");
                    if (TextPageUp(&g_tTextContent)) {
                        ShowTextPage();
                    }
                }
                else
                {
                    /* 点击了右半边，下翻页 */
                    DBG_PRINTF("Right side clicked, paging down\n");
                    if (TextPageDown(&g_tTextContent)) {
                        ShowTextPage();
                    }
                }
            }
        }
    }
    
    /* 8. 释放资源 */
    FreeTextContent(&g_tTextContent);
    
    /* 释放显存 */
    if (g_ptTextPageVideoMem)
    {
        PutVideoMem(g_ptTextPageVideoMem);
        g_ptTextPageVideoMem = NULL;
    }
    
    DBG_PRINTF("TextPageRun: exited cleanly\n");
}

static T_PageAction g_tTextPageAction = {
    .name          = "text",
    .Run           = TextPageRun,
    .GetInputEvent = TextPageGetInputEvent,
    .Prepare       = NULL,
};

/**********************************************************************
 * 函数名称： TextPageRegister
 * 功能描述： 注册"文本查看页面"
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 ***********************************************************************/
int TextPageRegister(void)
{
    return RegisterPageAction(&g_tTextPageAction);
}